home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / kern / uipc_socket2.c < prev    next >
C/C++ Source or Header  |  1993-12-18  |  25KB  |  948 lines

  1. RCS_ID_C="$Id: uipc_socket2.c,v 1.23 1993/12/18 15:28:09 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: uipc_socket2.c,v $
  9.  * Revision 1.23  1993/12/18  15:28:09  jraja
  10.  * Disabled code using M_EOR, unless USE_M_EOR is defined.
  11.  *
  12.  * Revision 1.22  1993/11/17  12:14:31  jraja
  13.  * Added check for the SB_SEL flag to the sowakeup() to prevent unnecessary
  14.  * calls to selwakeup().
  15.  *
  16.  * Revision 1.21  1993/11/17  09:21:47  jraja
  17.  * Added setting of SB_SEL to sbselqueue(), so that protocols would notify us.
  18.  * Added clearing of that flag in sowakeup() to prevent extra notifications.
  19.  *
  20.  * Revision 1.20  1993/06/04  11:16:15  jraja
  21.  * Fixes for first public release.
  22.  *
  23.  * Revision 1.19  1993/05/17  01:07:47  ppessi
  24.  * Changed RCS version.
  25.  *
  26.  * Revision 1.18  1993/04/26  11:54:52  too
  27.  * Changed include paths of amiga_api.h, amiga_libcallentry.h and amiga_raf.h
  28.  * from kern to api
  29.  *
  30.  * Revision 1.17  93/04/24  22:45:56  22:45:56  jraja (Jarno Tapio Rajahalme)
  31.  * Removed Define for USECLUSTERS
  32.  * 
  33.  * Revision 1.16  93/04/24  17:52:35  17:52:35  jraja (Jarno Tapio Rajahalme)
  34.  * Changed MCLBYTES to mbconf.mclbytes.
  35.  * 
  36.  * Revision 1.15  93/04/12  00:38:28  00:38:28  jraja (Jarno Tapio Rajahalme)
  37.  * Added #include <kern/amiga_includes.h> and <kern/amiga_api.h> for Signal().
  38.  * 
  39.  * Revision 1.14  93/04/12  00:29:36  00:29:36  jraja (Jarno Tapio Rajahalme)
  40.  * Added signalling of the task (SIGIO).
  41.  * 
  42.  * Revision 1.13  93/04/06  15:16:21  15:16:21  jraja (Jarno Tapio Rajahalme)
  43.  * Changed spl function return value storage to spl_t,
  44.  * changed bcopys and bzeros to aligned and/or const when possible,
  45.  * added inclusion of conf.h to every .c file.
  46.  * 
  47.  * Revision 1.12  93/03/17  12:07:33  12:07:33  jraja (Jarno Tapio Rajahalme)
  48.  * Fixed tsleep() call to find socket base if necessary and to give NULL
  49.  * timeout if timeval is all zeroes.
  50.  * 
  51.  * Revision 1.11  93/03/05  21:11:20  21:11:20  jraja (Jarno Tapio Rajahalme)
  52.  * Fixed includes (again).
  53.  * 
  54.  * Revision 1.10  93/03/04  09:51:35  09:51:35  jraja (Jarno Tapio Rajahalme)
  55.  * Removed some redundant includes.
  56.  * 
  57.  * Revision 1.9  93/03/03  16:12:10  16:12:10  jraja (Jarno Tapio Rajahalme)
  58.  * Changed sonewconn1() to sonewconn().
  59.  * 
  60.  * Revision 1.8  93/03/02  17:35:07  17:35:07  too (Tomi Ollila)
  61.  * Changed some %d:s to %ld:s.. compiled when SOCKBUF_DEBUG is defined.
  62.  * 
  63.  * Revision 1.7  93/02/27  11:04:08  11:04:08  too (Tomi Ollila)
  64.  * Added prototypes.
  65.  * 
  66.  * Revision 1.6  93/02/25  13:02:06  13:02:06  too (Tomi Ollila)
  67.  * Added static inlines, sys/cdefs etc.
  68.  * 
  69.  * Revision 1.5  93/02/24  16:33:56  16:33:56  too (Tomi Ollila)
  70.  * Compiles.
  71.  * 
  72.  * Revision 1.4  93/02/23  11:39:45  11:39:45  too (Tomi Ollila)
  73.  * added SocketBase pointer to sbwait() and sblock(), now shoud work w/ AmiTCP
  74.  * 
  75.  * Revision 1.3  93/01/09  12:57:35  12:57:35  jraja (Jarno Tapio Rajahalme)
  76.  * Added #ifdef USECLUSTERS to disable cluster dependant code.
  77.  * 
  78.  * Revision 1.2  92/11/20  15:14:52  15:14:52  jraja (Jarno Tapio Rajahalme)
  79.  * Added #ifndef AMITCP's to make this compile.
  80.  * 
  81.  * Revision 1.1  92/11/19  12:07:33  12:07:33  jraja (Jarno Tapio Rajahalme)
  82.  * Initial revision
  83.  * 
  84.  *
  85.  */
  86.  
  87. /* 
  88.  * Mach Operating System
  89.  * Copyright (c) 1992 Carnegie Mellon University
  90.  * All Rights Reserved.
  91.  * 
  92.  * Permission to use, copy, modify and distribute this software and its
  93.  * documentation is hereby granted, provided that both the copyright
  94.  * notice and this permission notice appear in all copies of the
  95.  * software, derivative works or modified versions, and any portions
  96.  * thereof, and that both notices appear in supporting documentation.
  97.  * 
  98.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  99.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  100.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  101.  * 
  102.  * Carnegie Mellon requests users of this software to return to
  103.  * 
  104.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  105.  *  School of Computer Science
  106.  *  Carnegie Mellon University
  107.  *  Pittsburgh PA 15213-3890
  108.  * 
  109.  * any improvements or extensions that they make and grant Carnegie Mellon 
  110.  * the rights to redistribute these changes.
  111.  */
  112. /*
  113.  * HISTORY
  114.  * Log:    uipc_socket2.c,v
  115.  * Revision 2.1  92/04/21  17:13:26  rwd
  116.  * BSDSS
  117.  * 
  118.  *
  119.  */
  120.  
  121. /*
  122.  * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
  123.  * All rights reserved.
  124.  *
  125.  * Redistribution and use in source and binary forms, with or without
  126.  * modification, are permitted provided that the following conditions
  127.  * are met:
  128.  * 1. Redistributions of source code must retain the above copyright
  129.  *    notice, this list of conditions and the following disclaimer.
  130.  * 2. Redistributions in binary form must reproduce the above copyright
  131.  *    notice, this list of conditions and the following disclaimer in the
  132.  *    documentation and/or other materials provided with the distribution.
  133.  * 3. All advertising materials mentioning features or use of this software
  134.  *    must display the following acknowledgement:
  135.  *    This product includes software developed by the University of
  136.  *    California, Berkeley and its contributors.
  137.  * 4. Neither the name of the University nor the names of its contributors
  138.  *    may be used to endorse or promote products derived from this software
  139.  *    without specific prior written permission.
  140.  *
  141.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  142.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  143.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  144.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  145.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  146.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  147.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  148.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  149.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  150.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  151.  * SUCH DAMAGE.
  152.  *
  153.  *    @(#)uipc_socket2.c    7.17 (Berkeley) 5/4/91
  154.  */
  155.  
  156. #include <conf.h>
  157.  
  158. #include <sys/param.h>
  159. #include <sys/systm.h>
  160. #include <sys/malloc.h>
  161. #include <sys/mbuf.h>
  162. #include <sys/protosw.h>
  163. #include <sys/socket.h>
  164. #include <sys/socketvar.h>
  165. #include <sys/synch.h>
  166.  
  167. #include <api/amiga_api.h>
  168. #include <kern/amiga_includes.h>
  169.  
  170. #include <kern/uipc_socket2_protos.h>
  171. #include <kern/amiga_select_protos.h>
  172.  
  173. /*
  174.  * Primitive routines for operating on sockets and socket buffers
  175.  */
  176.  
  177. /* strings for sleep message: */
  178. char    netio[] = "netio";
  179. char    netcon[] = "netcon";
  180. char    netcls[] = "netcls";
  181.  
  182. u_long    sb_max = SB_MAX;        /* patchable */
  183.  
  184. /*
  185.  * Procedures to manipulate state flags of socket
  186.  * and do appropriate wakeups.  Normal sequence from the
  187.  * active (originating) side is that soisconnecting() is
  188.  * called during processing of connect() call,
  189.  * resulting in an eventual call to soisconnected() if/when the
  190.  * connection is established.  When the connection is torn down
  191.  * soisdisconnecting() is called during processing of disconnect() call,
  192.  * and soisdisconnected() is called when the connection to the peer
  193.  * is totally severed.  The semantics of these routines are such that
  194.  * connectionless protocols can call soisconnected() and soisdisconnected()
  195.  * only, bypassing the in-progress calls when setting up a ``connection''
  196.  * takes no time.
  197.  *
  198.  * From the passive side, a socket is created with
  199.  * two queues of sockets: so_q0 for connections in progress
  200.  * and so_q for connections already made and awaiting user acceptance.
  201.  * As a protocol is preparing incoming connections, it creates a socket
  202.  * structure queued on so_q0 by calling sonewconn().  When the connection
  203.  * is established, soisconnected() is called, and transfers the
  204.  * socket structure to so_q, making it available to accept().
  205.  * 
  206.  * If a socket is closed with sockets on either
  207.  * so_q0 or so_q, these sockets are dropped.
  208.  *
  209.  * If higher level protocols are implemented in
  210.  * the kernel, the wakeups done here will sometimes
  211.  * cause software-interrupt process scheduling.
  212.  */
  213.  
  214. void
  215. soisconnecting(so)
  216.     register struct socket *so;
  217. {
  218.  
  219.     so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
  220.     so->so_state |= SS_ISCONNECTING;
  221. }
  222.  
  223. void
  224. soisconnected(so)
  225.     register struct socket *so;
  226. {
  227.     register struct socket *head = so->so_head;
  228.  
  229.     so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
  230.     so->so_state |= SS_ISCONNECTED;
  231.     if (head && soqremque(so, 0)) {
  232.         soqinsque(head, so, 1);
  233.         sorwakeup(head);
  234.         wakeup((caddr_t)&head->so_timeo);
  235.     } else {
  236.         wakeup((caddr_t)&so->so_timeo);
  237.         sorwakeup(so);
  238.         sowwakeup(so);
  239.     }
  240. }
  241.  
  242. void
  243. soisdisconnecting(so)
  244.     register struct socket *so;
  245. {
  246.  
  247.     so->so_state &= ~SS_ISCONNECTING;
  248.     so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
  249.     wakeup((caddr_t)&so->so_timeo);
  250.     sowwakeup(so);
  251.     sorwakeup(so);
  252. }
  253.  
  254. void
  255. soisdisconnected(so)
  256.     register struct socket *so;
  257. {
  258.  
  259.     so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
  260.     so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
  261.     wakeup((caddr_t)&so->so_timeo);
  262.     sowwakeup(so);
  263.     sorwakeup(so);
  264. }
  265.  
  266. /*
  267.  * When an attempt at a new connection is noted on a socket
  268.  * which accepts connections, sonewconn is called.  If the
  269.  * connection is possible (subject to space constraints, etc.)
  270.  * then we allocate a new structure, propoerly linked into the
  271.  * data structure of the original socket, and return this.
  272.  * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
  273.  */
  274. struct socket *
  275. sonewconn(head, connstatus)
  276.     register struct socket *head;
  277.     int connstatus;
  278. {
  279.     register struct socket *so;
  280.     int soqueue = connstatus ? 1 : 0;
  281.  
  282.     if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
  283.         return ((struct socket *)0);
  284.     MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT);
  285.     if (so == NULL) 
  286.         return ((struct socket *)0);
  287.     aligned_bzero_const((caddr_t)so, sizeof(*so));
  288.     so->so_type = head->so_type;
  289.     so->so_options = head->so_options &~ SO_ACCEPTCONN;
  290.     so->so_linger = head->so_linger;
  291.     so->so_state = head->so_state | SS_NOFDREF;
  292.     so->so_proto = head->so_proto;
  293.     so->so_timeo = head->so_timeo;
  294.     so->so_pgid = head->so_pgid;
  295.     (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
  296.     soqinsque(head, so, soqueue);
  297.     if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
  298.         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
  299.         (void) soqremque(so, soqueue);
  300.         (void) bsd_free((caddr_t)so, M_SOCKET);
  301.         return ((struct socket *)0);
  302.     }
  303.     if (connstatus) {
  304.         sorwakeup(head);
  305.         wakeup((caddr_t)&head->so_timeo);
  306.         so->so_state |= connstatus;
  307.     }
  308.     return (so);
  309. }
  310.  
  311. void
  312. soqinsque(head, so, q)
  313.     register struct socket *head, *so;
  314.     int q;
  315. {
  316.  
  317.     register struct socket **prev;
  318.     so->so_head = head;
  319.     if (q == 0) {
  320.         head->so_q0len++;
  321.         so->so_q0 = 0;
  322.         for (prev = &(head->so_q0); *prev; )
  323.             prev = &((*prev)->so_q0);
  324.     } else {
  325.         head->so_qlen++;
  326.         so->so_q = 0;
  327.         for (prev = &(head->so_q); *prev; )
  328.             prev = &((*prev)->so_q);
  329.     }
  330.     *prev = so;
  331. }
  332.  
  333. int
  334. soqremque(so, q)
  335.     register struct socket *so;
  336.     int q;
  337. {
  338.     register struct socket *head, *prev, *next;
  339.  
  340.     head = so->so_head;
  341.     prev = head;
  342.     for (;;) {
  343.         next = q ? prev->so_q : prev->so_q0;
  344.         if (next == so)
  345.             break;
  346.         if (next == 0)
  347.             return (0);
  348.         prev = next;
  349.     }
  350.     if (q == 0) {
  351.         prev->so_q0 = next->so_q0;
  352.         head->so_q0len--;
  353.     } else {
  354.         prev->so_q = next->so_q;
  355.         head->so_qlen--;
  356.     }
  357.     next->so_q0 = next->so_q = 0;
  358.     next->so_head = 0;
  359.     return (1);
  360. }
  361.  
  362. /*
  363.  * Socantsendmore indicates that no more data will be sent on the
  364.  * socket; it would normally be applied to a socket when the user
  365.  * informs the system that no more data is to be sent, by the protocol
  366.  * code (in case PRU_SHUTDOWN).  Socantrcvmore indicates that no more data
  367.  * will be received, and will normally be applied to the socket by a
  368.  * protocol when it detects that the peer will send no more data.
  369.  * Data queued for reading in the socket may yet be read.
  370.  */
  371.  
  372. void
  373. socantsendmore(so)
  374.     struct socket *so;
  375. {
  376.  
  377.     so->so_state |= SS_CANTSENDMORE;
  378.     sowwakeup(so);
  379. }
  380.  
  381. void
  382. socantrcvmore(so)
  383.     struct socket *so;
  384. {
  385.  
  386.     so->so_state |= SS_CANTRCVMORE;
  387.     sorwakeup(so);
  388. }
  389.  
  390. /*
  391.  * Socket select/wakeup routines.
  392.  */
  393.  
  394. /*
  395.  * Queue a process for a select on a socket buffer.
  396.  */
  397. void
  398. sbselqueue(sb, cp)
  399.      struct sockbuf *sb;
  400.      struct SocketBase *cp;
  401. {
  402.   selenter(cp, &sb->sb_sel);
  403.   sb->sb_flags |= SB_SEL; /* notify us if something happens */
  404. }
  405.  
  406. /*
  407.  * Wait for data to arrive at/drain from a socket buffer.
  408.  */
  409. int
  410. sbwait(sb, cp)
  411.      struct sockbuf *sb;
  412.      struct SocketBase *cp;
  413. {
  414.  
  415.   sb->sb_flags |= SB_WAIT;
  416.   return (tsleep(cp, (caddr_t)&sb->sb_cc, netio, 
  417.          (sb->sb_timeo.tv_sec || sb->sb_timeo.tv_usec) ?
  418.          &sb->sb_timeo : NULL));
  419. }
  420.  
  421. /* 
  422.  * Lock a sockbuf already known to be locked;
  423.  * return any error returned from sleep (EINTR).
  424.  */
  425. int
  426. sb_lock(sb, cp)
  427.      struct sockbuf *sb;
  428.      struct SocketBase *cp;
  429. {
  430.     int error;
  431.  
  432.     while (sb->sb_flags & SB_LOCK) {
  433.         sb->sb_flags |= SB_WANT;
  434.         if (error = tsleep(cp, (caddr_t)&sb->sb_flags, netio, NULL))
  435.             return (error);
  436.     }
  437.     sb->sb_flags |= SB_LOCK;
  438.     return (0);
  439. }
  440.  
  441. /*
  442.  * Wakeup processes waiting on a socket buffer.
  443.  * Do asynchronous notification via SIGIO
  444.  * if the socket has the SS_ASYNC flag set.
  445.  */
  446. void
  447. sowakeup(so, sb)
  448.     register struct socket *so;
  449.     register struct sockbuf *sb;
  450. {
  451. #ifndef AMITCP
  452.         struct proc *p;
  453. #endif
  454.     if (sb->sb_flags & SB_SEL) {
  455.         sb->sb_flags &= ~SB_SEL; /* do not notify us any more */
  456.         selwakeup(&sb->sb_sel);
  457.     }
  458.     if (sb->sb_flags & SB_WAIT) {
  459.         sb->sb_flags &= ~SB_WAIT;
  460.         wakeup((caddr_t)&sb->sb_cc);
  461.     }
  462.     if (so->so_state & SS_ASYNC) {
  463. #ifdef AMITCP
  464.         if (so->so_pgid)
  465.             Signal(so->so_pgid->thisTask, so->so_pgid->sigIOMask);
  466. #else
  467.         if (so->so_pgid < 0)
  468.             gsignal(-so->so_pgid, SIGIO);
  469.         else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
  470.             psignal(p, SIGIO);
  471. #endif
  472.     }
  473. }
  474.  
  475. /*
  476.  * Socket buffer (struct sockbuf) utility routines.
  477.  *
  478.  * Each socket contains two socket buffers: one for sending data and
  479.  * one for receiving data.  Each buffer contains a queue of mbufs,
  480.  * information about the number of mbufs and amount of data in the
  481.  * queue, and other fields allowing select() statements and notification
  482.  * on data availability to be implemented.
  483.  *
  484.  * Data stored in a socket buffer is maintained as a list of records.
  485.  * Each record is a list of mbufs chained together with the m_next
  486.  * field.  Records are chained together with the m_nextpkt field. The upper
  487.  * level routine soreceive() expects the following conventions to be
  488.  * observed when placing information in the receive buffer:
  489.  *
  490.  * 1. If the protocol requires each message be preceded by the sender's
  491.  *    name, then a record containing that name must be present before
  492.  *    any associated data (mbuf's must be of type MT_SONAME).
  493.  * 2. If the protocol supports the exchange of ``access rights'' (really
  494.  *    just additional data associated with the message), and there are
  495.  *    ``rights'' to be received, then a record containing this data
  496.  *    should be present (mbuf's must be of type MT_RIGHTS).
  497.  * 3. If a name or rights record exists, then it must be followed by
  498.  *    a data record, perhaps of zero length.
  499.  *
  500.  * Before using a new socket structure it is first necessary to reserve
  501.  * buffer space to the socket, by calling sbreserve().  This should commit
  502.  * some of the available buffer space in the system buffer pool for the
  503.  * socket (currently, it does nothing but enforce limits).  The space
  504.  * should be released by calling sbrelease() when the socket is destroyed.
  505.  */
  506.  
  507. int
  508. soreserve(so, sndcc, rcvcc)
  509.     register struct socket *so;
  510.     u_long sndcc, rcvcc;
  511. {
  512.  
  513.     if (sbreserve(&so->so_snd, sndcc) == 0)
  514.         goto bad;
  515.     if (sbreserve(&so->so_rcv, rcvcc) == 0)
  516.         goto bad2;
  517.     if (so->so_rcv.sb_lowat == 0)
  518.         so->so_rcv.sb_lowat = 1;
  519.     if (so->so_snd.sb_lowat == 0)
  520.         so->so_snd.sb_lowat = mbconf.mclbytes;
  521.     if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
  522.         so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
  523.     return (0);
  524. bad2:
  525.     sbrelease(&so->so_snd);
  526. bad:
  527.     return (ENOBUFS);
  528. }
  529.  
  530. /*
  531.  * Allot mbufs to a sockbuf.
  532.  * Attempt to scale mbmax so that mbcnt doesn't become limiting
  533.  * if buffering efficiency is near the normal case.
  534.  */
  535. int
  536. sbreserve(sb, cc)
  537.     struct sockbuf *sb;
  538.     u_long cc;
  539. {
  540.  
  541.     if (cc > sb_max * mbconf.mclbytes / (MSIZE + mbconf.mclbytes))
  542.         return (0);
  543.     sb->sb_hiwat = cc;
  544.     sb->sb_mbmax = min(cc * 2, sb_max);
  545.     if (sb->sb_lowat > sb->sb_hiwat)
  546.         sb->sb_lowat = sb->sb_hiwat;
  547.     return (1);
  548. }
  549.  
  550. /*
  551.  * Free mbufs held by a socket, and reserved mbuf space.
  552.  */
  553. void
  554. sbrelease(sb)
  555.     struct sockbuf *sb;
  556. {
  557.  
  558.     sbflush(sb);
  559.     sb->sb_hiwat = sb->sb_mbmax = 0;
  560. }
  561.  
  562. /*
  563.  * Routines to add and remove
  564.  * data from an mbuf queue.
  565.  *
  566.  * The routines sbappend() or sbappendrecord() are normally called to
  567.  * append new mbufs to a socket buffer, after checking that adequate
  568.  * space is available, comparing the function sbspace() with the amount
  569.  * of data to be added.  sbappendrecord() differs from sbappend() in
  570.  * that data supplied is treated as the beginning of a new record.
  571.  * To place a sender's address, optional access rights, and data in a
  572.  * socket receive buffer, sbappendaddr() should be used.  To place
  573.  * access rights and data in a socket receive buffer, sbappendrights()
  574.  * should be used.  In either case, the new data begins a new record.
  575.  * Note that unlike sbappend() and sbappendrecord(), these routines check
  576.  * for the caller that there will be enough space to store the data.
  577.  * Each fails if there is not enough space, or if it cannot find mbufs
  578.  * to store additional information in.
  579.  *
  580.  * Reliable protocols may use the socket send buffer to hold data
  581.  * awaiting acknowledgement.  Data is normally copied from a socket
  582.  * send buffer in a protocol with m_copy for output to a peer,
  583.  * and then removing the data from the socket buffer with sbdrop()
  584.  * or sbdroprecord() when the data is acknowledged by the peer.
  585.  */
  586.  
  587. /*
  588.  * Append mbuf chain m to the last record in the
  589.  * socket buffer sb.  The additional space associated
  590.  * the mbuf chain is recorded in sb.  Empty mbufs are
  591.  * discarded and mbufs are compacted where possible.
  592.  */
  593. void
  594. sbappend(sb, m)
  595.     struct sockbuf *sb;
  596.     struct mbuf *m;
  597. {
  598.     register struct mbuf *n;
  599.  
  600.     if (m == 0)
  601.         return;
  602.     if (n = sb->sb_mb) {
  603.         while (n->m_nextpkt)
  604.             n = n->m_nextpkt;
  605.         do {
  606. #ifdef USE_M_EOR
  607.             if (n->m_flags & M_EOR) {
  608.                 sbappendrecord(sb, m); /* XXXXXX!!!! */
  609.                 return;
  610.             }
  611. #endif
  612.         } while (n->m_next && (n = n->m_next));
  613.     }
  614.     sbcompress(sb, m, n);
  615. }
  616.  
  617. #ifdef SOCKBUF_DEBUG
  618. void
  619. sbcheck(sb)
  620.     register struct sockbuf *sb;
  621. {
  622.     register struct mbuf *m;
  623.     register int len = 0, mbcnt = 0;
  624.  
  625.     for (m = sb->sb_mb; m; m = m->m_next) {
  626.         len += m->m_len;
  627.         mbcnt += MSIZE;
  628.         if (m->m_flags & M_EXT)
  629.             mbcnt += m->m_ext.ext_size;
  630.         if (m->m_nextpkt)
  631.             panic("sbcheck nextpkt");
  632.     }
  633.     if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
  634.         printf("cc %ld != %ld || mbcnt %ld != %ld\n", len, sb->sb_cc,
  635.             mbcnt, sb->sb_mbcnt);
  636.         panic("sbcheck");
  637.     }
  638. }
  639. #endif
  640.  
  641. /*
  642.  * As above, except the mbuf chain
  643.  * begins a new record.
  644.  */
  645. void
  646. sbappendrecord(sb, m0)
  647.     register struct sockbuf *sb;
  648.     register struct mbuf *m0;
  649. {
  650.     register struct mbuf *m;
  651.  
  652.     if (m0 == 0)
  653.         return;
  654.     if (m = sb->sb_mb)
  655.         while (m->m_nextpkt)
  656.             m = m->m_nextpkt;
  657.     /*
  658.      * Put the first mbuf on the queue.
  659.      * Note this permits zero length records.
  660.      */
  661.     sballoc(sb, m0);
  662.     if (m)
  663.         m->m_nextpkt = m0;
  664.     else
  665.         sb->sb_mb = m0;
  666.     m = m0->m_next;
  667.     m0->m_next = 0;
  668. #ifdef USE_M_EOR
  669.     if (m && (m0->m_flags & M_EOR)) {
  670.         m0->m_flags &= ~M_EOR;
  671.         m->m_flags |= M_EOR;
  672.     }
  673. #endif
  674.     sbcompress(sb, m, m0);
  675. }
  676.  
  677. /*
  678.  * As above except that OOB data
  679.  * is inserted at the beginning of the sockbuf,
  680.  * but after any other OOB data.
  681.  */
  682. void
  683. sbinsertoob(sb, m0)
  684.     register struct sockbuf *sb;
  685.     register struct mbuf *m0;
  686. {
  687.     register struct mbuf *m;
  688.     register struct mbuf **mp;
  689.  
  690.     if (m0 == 0)
  691.         return;
  692.     for (mp = &sb->sb_mb; m = *mp; mp = &((*mp)->m_nextpkt)) {
  693.         again:
  694.         switch (m->m_type) {
  695.  
  696.         case MT_OOBDATA:
  697.             continue;        /* WANT next train */
  698.  
  699.         case MT_CONTROL:
  700.             if (m = m->m_next)
  701.                 goto again;    /* inspect THIS train further */
  702.         }
  703.         break;
  704.     }
  705.     /*
  706.      * Put the first mbuf on the queue.
  707.      * Note this permits zero length records.
  708.      */
  709.     sballoc(sb, m0);
  710.     m0->m_nextpkt = *mp;
  711.     *mp = m0;
  712.     m = m0->m_next;
  713.     m0->m_next = 0;
  714. #ifdef USE_M_EOR
  715.     if (m && (m0->m_flags & M_EOR)) {
  716.         m0->m_flags &= ~M_EOR;
  717.         m->m_flags |= M_EOR;
  718.     }
  719. #endif
  720.     sbcompress(sb, m, m0);
  721. }
  722.  
  723. /*
  724.  * Append address and data, and optionally, control (ancillary) data
  725.  * to the receive queue of a socket.  If present,
  726.  * m0 must include a packet header with total length.
  727.  * Returns 0 if no space in sockbuf or insufficient mbufs.
  728.  */
  729. int
  730. sbappendaddr(sb, asa, m0, control)
  731.     register struct sockbuf *sb;
  732.     struct sockaddr *asa;
  733.     struct mbuf *m0, *control;
  734. {
  735.     register struct mbuf *m, *n;
  736.     int space = asa->sa_len;
  737.  
  738. if (m0 && (m0->m_flags & M_PKTHDR) == 0)
  739. panic("sbappendaddr");
  740.     if (m0)
  741.         space += m0->m_pkthdr.len;
  742.     for (n = control; n; n = n->m_next) {
  743.         space += n->m_len;
  744.         if (n->m_next == 0)    /* keep pointer to last control buf */
  745.             break;
  746.     }
  747.     if (space > sbspace(sb))
  748.         return (0);
  749.     if (asa->sa_len > MLEN)
  750.         return (0);
  751.     MGET(m, M_DONTWAIT, MT_SONAME);
  752.     if (m == 0)
  753.         return (0);
  754.     m->m_len = asa->sa_len;
  755.     aligned_bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
  756.     if (n)
  757.         n->m_next = m0;        /* concatenate data to control */
  758.     else
  759.         control = m0;
  760.     m->m_next = control;
  761.     for (n = m; n; n = n->m_next)
  762.         sballoc(sb, n);
  763.     if (n = sb->sb_mb) {
  764.         while (n->m_nextpkt)
  765.             n = n->m_nextpkt;
  766.         n->m_nextpkt = m;
  767.     } else
  768.         sb->sb_mb = m;
  769.     return (1);
  770. }
  771.  
  772. int
  773. sbappendcontrol(sb, m0, control)
  774.     struct sockbuf *sb;
  775.     struct mbuf *control, *m0;
  776. {
  777.     register struct mbuf *m, *n;
  778.     int space = 0;
  779.  
  780.     if (control == 0)
  781.         panic("sbappendcontrol");
  782.     for (m = control; ; m = m->m_next) {
  783.         space += m->m_len;
  784.         if (m->m_next == 0)
  785.             break;
  786.     }
  787.     n = m;            /* save pointer to last control buffer */
  788.     for (m = m0; m; m = m->m_next)
  789.         space += m->m_len;
  790.     if (space > sbspace(sb))
  791.         return (0);
  792.     n->m_next = m0;            /* concatenate data to control */
  793.     for (m = control; m; m = m->m_next)
  794.         sballoc(sb, m);
  795.     if (n = sb->sb_mb) {
  796.         while (n->m_nextpkt)
  797.             n = n->m_nextpkt;
  798.         n->m_nextpkt = control;
  799.     } else
  800.         sb->sb_mb = control;
  801.     return (1);
  802. }
  803.  
  804. /*
  805.  * Compress mbuf chain m into the socket
  806.  * buffer sb following mbuf n.  If n
  807.  * is null, the buffer is presumed empty.
  808.  */
  809. void
  810. sbcompress(sb, m, n)
  811.     register struct sockbuf *sb;
  812.     register struct mbuf *m, *n;
  813. {
  814. #ifdef USE_M_EOR
  815.     register int eor = 0;
  816. #endif
  817.     register struct mbuf *o;
  818.  
  819.     while (m) {
  820. #ifdef USE_M_EOR
  821.         eor |= m->m_flags & M_EOR;
  822. #endif
  823.         if (m->m_len == 0 &&
  824.             (
  825. #ifdef USE_M_EOR
  826.              eor == 0 ||
  827. #endif
  828.              (((o = m->m_next) || (o = n)) &&
  829.               o->m_type == m->m_type))) {
  830.             m = m_free(m);
  831.             continue;
  832.         }
  833.         if (n && (n->m_flags & (M_EXT
  834. #ifdef USE_M_EOR
  835.  |    M_EOR
  836. #endif
  837.                     )) == 0 &&
  838.             (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] &&
  839.             n->m_type == m->m_type) {
  840.             bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
  841.                 (unsigned)m->m_len);
  842.             n->m_len += m->m_len;
  843.             sb->sb_cc += m->m_len;
  844.             m = m_free(m);
  845.             continue;
  846.         }
  847.         if (n)
  848.             n->m_next = m;
  849.         else
  850.             sb->sb_mb = m;
  851.         sballoc(sb, m);
  852.         n = m;
  853. #ifdef USE_M_EOR
  854.         m->m_flags &= ~M_EOR;
  855. #endif
  856.         m = m->m_next;
  857.         n->m_next = 0;
  858.     }
  859. #ifdef USE_M_EOR
  860.     if (eor) {
  861.         if (n)
  862.             n->m_flags |= eor;
  863.         else
  864.             printf("semi-panic: sbcompress\n");
  865.     }
  866. #endif
  867. }
  868.  
  869. /*
  870.  * Free all mbufs in a sockbuf.
  871.  * Check that all resources are reclaimed.
  872.  */
  873. void
  874. sbflush(sb)
  875.     register struct sockbuf *sb;
  876. {
  877.  
  878.     if (sb->sb_flags & SB_LOCK)
  879.         panic("sbflush");
  880.     while (sb->sb_mbcnt)
  881.         sbdrop(sb, (int)sb->sb_cc);
  882.     if (sb->sb_cc || sb->sb_mb)
  883.         panic("sbflush 2");
  884. }
  885.  
  886. /*
  887.  * Drop data from (the front of) a sockbuf.
  888.  */
  889. void
  890. sbdrop(sb, len)
  891.     register struct sockbuf *sb;
  892.     register int len;
  893. {
  894.     register struct mbuf *m, *mn;
  895.     struct mbuf *next;
  896.  
  897.     next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
  898.     while (len > 0) {
  899.         if (m == 0) {
  900.             if (next == 0)
  901.                 panic("sbdrop");
  902.             m = next;
  903.             next = m->m_nextpkt;
  904.             continue;
  905.         }
  906.         if (m->m_len > len) {
  907.             m->m_len -= len;
  908.             m->m_data += len;
  909.             sb->sb_cc -= len;
  910.             break;
  911.         }
  912.         len -= m->m_len;
  913.         sbfree(sb, m);
  914.         MFREE(m, mn);
  915.         m = mn;
  916.     }
  917.     while (m && m->m_len == 0) {
  918.         sbfree(sb, m);
  919.         MFREE(m, mn);
  920.         m = mn;
  921.     }
  922.     if (m) {
  923.         sb->sb_mb = m;
  924.         m->m_nextpkt = next;
  925.     } else
  926.         sb->sb_mb = next;
  927. }
  928.  
  929. /*
  930.  * Drop a record off the front of a sockbuf
  931.  * and move the next record to the front.
  932.  */
  933. void
  934. sbdroprecord(sb)
  935.     register struct sockbuf *sb;
  936. {
  937.     register struct mbuf *m, *mn;
  938.  
  939.     m = sb->sb_mb;
  940.     if (m) {
  941.         sb->sb_mb = m->m_nextpkt;
  942.         do {
  943.             sbfree(sb, m);
  944.             MFREE(m, mn);
  945.         } while (m = mn);
  946.     }
  947. }
  948.